package hos.thread

import android.content.Context
import android.util.AttributeSet
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.annotation.LayoutRes
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.LayoutInflaterCompat
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext

/**
 * <p>Title: CoroutineLayoutInflater </p>
 * <p>Description:  </p>
 * <p>Company: www.mapuni.com </p>
 *
 * @author : 蔡俊峰
 * @date : 2024-08-05 20:07
 * @version : 1.0
 */
class CoroutineLayoutInflater @JvmOverloads constructor(
    context: Context,
    private val dispatcher: CoroutineDispatcher = Dispatchers.Default
) {

    private val inflater = BasicInflater(context)

    init {
        ((context as? AppCompatActivity)?.delegate as? LayoutInflater.Factory2)?.let { factory2 ->
            LayoutInflaterCompat.setFactory2(inflater, factory2)
        }
    }

    @JvmOverloads
    suspend fun inflate(@LayoutRes resId: Int, parent: ViewGroup? = null): View {
        val view = withContext(dispatcher) {
            try {
                inflater.inflate(resId, parent, false)
            } catch (ex: RuntimeException) {
                Log.e(
                    "CoroutineLayoutInflater",
                    "The background thread failed to inflate. Error message=${ex.message}"
                )
                null
            }
        }
        //如果在main线程了直接调度
        return withContext(Dispatchers.Main.immediate) {
            view ?: inflater.inflate(resId, parent, false)
        }
    }

    private class BasicInflater(context: Context?) :
        LayoutInflater(context) {

        override fun cloneInContext(newContext: Context): LayoutInflater {
            return BasicInflater(newContext)
        }

        override fun onCreateView(name: String, attrs: AttributeSet): View {
            for (prefix in sClassPrefixList) {
                try {
                    val view = createView(name, prefix, attrs)
                    if (view != null) {
                        return view
                    }
                } catch (e: ClassNotFoundException) {
                    // In this case we want to let the base class take a crack
                    // at it.
                }
            }
            return super.onCreateView(name, attrs)
        }

        companion object {
            @JvmStatic
            private val sClassPrefixList = arrayOf(
                "android.widget.",
                "android.webkit.",
                "android.app."
            )
        }
    }

}